package com.ruoyi.combat.service.externalServiceInvoker;


import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import cn.hutool.json.JSONUtil;
import com.ruoyi.combat.domain.CombatMethod;
import com.ruoyi.combat.mapper.CombatMethodMapper;
import com.ruoyi.combat.util.MethodUseUtils;
import com.ruoyi.common.exception.base.BaseException;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author baijie
 * @date 2025/2/19
 * @description 请求外部接口，进行抗定位操作
 */

@Service
public class AntiPositioningService {

    private static final Logger log = LoggerFactory.getLogger(AntiPositioningService.class);
    @Autowired
    private CombatMethodMapper combatMethodMapper;
    @Autowired
    private MethodUseUtils methodUseUtils;

    /**
     * 基于虚假地标的抗定位
     *
     * @param targetIP 目标IP
     * @param clIPList 虚假IP List
     */
    public void antiPositioning(String targetIP, List<String> clIPList, String cityName, String lon, String lat, Long taskId) {
        try {
            cityName = convertToPinyin(cityName);
            // 使用String.join将List转换为以分号分隔的字符串
            String result = String.join(";", clIPList);
            // 获取外部请求接口信息
            CombatMethod combatMethod = combatMethodMapper.selectCombatMethodById(20L);
            if (combatMethod == null) {
                log.error("未查询到基于虚假地标的抗定位算法");
                throw new BaseException("未查询到基于虚假地标的抗定位算法");
            }
            String methodUrl = combatMethod.getMethodUrl();
            if (StrUtil.isBlank(methodUrl)) {
                log.error("未查询到基于虚假地标的抗定位算法的请求地址");
                throw new BaseException("未查询到基于虚假地标的抗定位算法的请求地址");
            }
            // 封装请求参数并进行URL编码
            String encodedTargetIP = URLEncoder.encode(targetIP, StandardCharsets.UTF_8.toString());
            String encodedClIPs = URLEncoder.encode(result, StandardCharsets.UTF_8.toString());
            String postParam = "targetIP=" + encodedTargetIP + "&clIPList=" + encodedClIPs + "&cityName=" + cityName + "&lon=" + lon + "&lat=" + lat + "&taskId=" + taskId;
            // 调用算法
            Map<String, Object> map = methodUseUtils.methodUseLogs(20L, postParam);
            Integer code = (Integer) map.get("code");
            String message = (String) map.get("message");
            if (200 == code) {
                log.info("基于虚假地标的抗定位请求成功");
            } else {
                log.error("基于虚假地标的抗定位请求失败:" + message);
                throw new BaseException("基于虚假地标的抗定位请求失败:" + message);
            }
        } catch (Exception e) {
            log.error("基于虚假地标的抗定位请求过程中发生异常", e);
            throw new BaseException("基于虚假地标的抗定位请求过程中发生异常");
        }

    }

    /**
     * 基于时延混淆的抗定位
     *
     * @param targetIP  目标IP
     * @param delayTime 延迟时间 单位毫秒
     */
    public void antiPositioningByDelay(String targetIP, Long delayTime, String cityName, String lon, String lat, Long taskId) {
        try {
            cityName = convertToPinyin(cityName);
            // 获取外部请求接口信息
            CombatMethod combatMethod = combatMethodMapper.selectCombatMethodById(21L);
            if (combatMethod == null) {
                log.error("未查询到基于时延混淆的抗定位算法");
                throw new BaseException("未查询到基于时延混淆的抗定位算法");
            }
            String methodUrl = combatMethod.getMethodUrl();
            if (StrUtil.isBlank(methodUrl)) {
                log.error("未查询到基于时延混淆的抗定位算法请求地址");
                throw new BaseException("未查询到基于时延混淆的抗定位算法请求地址");
            }
            String encodedTargetIP = URLEncoder.encode(targetIP, StandardCharsets.UTF_8.toString());
            Map<String, Object> mapParam = new HashMap<>();
            mapParam.put("targetIP", encodedTargetIP);
            mapParam.put("delay", delayTime);
            Map<String, Object> map = methodUseUtils.methodUseLogs(21L, JSONUtil.toJsonStr(mapParam));
            Integer code = (Integer) map.get("code");
            String message = (String) map.get("message");
            if (200 == code) {
                log.info("基于时延混淆的抗定位请求成功");
            } else {
                log.error("基于时延混淆的抗定位请求失败:" + message);
                throw new BaseException("基于时延混淆的抗定位请求失败:" + message);
            }
        } catch (Exception e) {
            log.error("基于时延混淆的抗定位请求过程中发生异常", e);
            throw new BaseException("基于时延混淆的抗定位请求过程中发生异常");
        }
    }

    /**
     * 汉字转拼音
     */
    public String convertToPinyin(String cityName) {
        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
        // 设置拼音小写
        format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        // 设置不带声调
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);

        StringBuilder pinyin = new StringBuilder();
        for (char c : cityName.toCharArray()) {
            try {
                String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c, format);
                if (pinyinArray != null && pinyinArray.length > 0) {
                    pinyin.append(pinyinArray[0]);
                } else {
                    pinyin.append(c);
                }
            } catch (BadHanyuPinyinOutputFormatCombination e) {
                log.error("汉字转拼音失败", e);
                throw new BaseException("汉字转拼音失败");
            }
        }
        String result = pinyin.toString();
        // 首字母大写
        result = result.toString().substring(0, 1).toUpperCase() + result.substring(1);
        return result;
    }
}
